﻿using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using Yz.Base;
using Yz.Base.ParaModels;
using Yz.Core.Extensions;
using Yz.Core.Tools;

namespace Yz.FileService.Middlewares
{
    /// <summary>
    /// 单文件上传（小文件）
    /// </summary>
    public class UploadMiddleware : BaseUploadMiddleware, IMiddleware
    {

        public async Task InvokeAsync(HttpContext context, RequestDelegate next)
        {
            #region 跨域上传
            if (context.Request.Method.Equals(HttpMethods.Options, StringComparison.OrdinalIgnoreCase))
            {
                base.AddHttpOptionHeader(context);
            }
            #endregion

            #region 后台post上传
            else if (context.Request.Method.Equals(HttpMethods.Post, StringComparison.OrdinalIgnoreCase))
            {
                try
                {
                    #region 验证token
                    var validRes = await ValidateTokenAsync(context);
                    if (!validRes.Item1.IsEmpty())
                    {
                        await context.Response.WriteAsync(new VmUpFileBase()
                        {
                            Msg = validRes.Item1
                        }.ToJsonStr());
                        return;
                    }
                    string appId = validRes.Item2;
                    #endregion

                    #region 文件验证
                    //获取上传的文件
                    var file = context.Request.Form.Files.FirstOrDefault();
                    if (file == null || file.Length == 0)
                    {
                        await context.Response.WriteAsync(new VmUpFileBase()
                        {
                            Msg = "上传文件不能为空！"
                        }.ToJsonStr());
                        return;
                    }
                    //后缀验证
                    var ext = Path.GetExtension(file.FileName).ToLower();
                    var fileLimit = _uploadConfig.Limits.Where(p => p.Value.AllowExts.Contains(ext)).FirstOrDefault();
                    if (string.IsNullOrEmpty(ext) || string.IsNullOrEmpty(fileLimit.Key))
                    {
                        await context.Response.WriteAsync(new VmUpFileBase()
                        {
                            Msg = "不支持此文件类型！"
                        }.ToJsonStr());
                        return;
                    }

                    //大小验证
                    if (file.Length > fileLimit.Value.Size * 1024)
                    {
                        int fileSize = (fileLimit.Value.Size / 1024).ToInt();
                        await context.Response.WriteAsync(new VmUpFileBase()
                        {
                            Msg = $"此文件类型不能超过{fileSize}M"
                        }.ToJsonStr());
                        return;
                    }
                    #endregion

                    #region 保存文件
                    //上传逻辑
                    var dtNow = DateTime.Now;
                    var folderPath = "/" + appId + "/" + dtNow.ToString("yyyy") + "/" + dtNow.ToString("MM") + "/" + dtNow.ToString("dd") + "/";
                    var localFolderPath = _uploadConfig.PhysicalPath + folderPath;
                    if (!Directory.Exists(localFolderPath))
                    {
                        Directory.CreateDirectory(localFolderPath);
                    }
                    var fileName = Guid.NewGuid().ToString("n") + ext;
                    var filePath = Path.Combine(localFolderPath, fileName);
                    using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
                    {
                        file.CopyTo(fileStream);
                        fileStream.Flush(true);
                    }
                    FileType fileType = FileType.None;
                    if (FileTypeList.ImgList.Contains(ext))
                    {
                        fileType = FileType.Pic;
                        var sv = context.Request.Form["application/json"].FirstOrDefault();
                        if (sv.IsEmpty())
                        {
                            sv = context.Request.Form["data"].FirstOrDefault();
                        }
                        if (!sv.IsEmpty())
                        {
                            var paraFile = sv.ToJsonObject<List<ParaThFile>>();
                            if (paraFile != null)
                            {
                                foreach (var item in paraFile)
                                {
                                    var thPath = Path.Combine(localFolderPath, Guid.NewGuid().ToString("n") + ext + "." + item.Width + "_" + item.Height + ext);

                                    using (FileStream fs = File.OpenRead(filePath))
                                    {
                                        Image image = Image.Load(fs);
                                        image.Mutate(a => a.Resize(item.Width, item.Height));
                                        image.Save(thPath);
                                        fs.Flush();
                                    }
                                }
                            }
                        }
                    }
                    else if (FileTypeList.DocList.Contains(ext))
                    {
                        fileType = FileType.Doc;
                    }
                    else if (FileTypeList.VdoList.Contains(ext))
                    {
                        fileType = FileType.Vdo;
                    }
                    else if (FileTypeList.RarList.Contains(ext))
                    {
                        fileType = FileType.Rar;
                    }
                    else if (FileTypeList.RdoList.Contains(ext))
                    {
                        fileType = FileType.Rdo;
                    }
                    var fileUrl = _uploadConfig.VirtualPath + folderPath + fileName;
                    await context.Response.WriteAsync(new VmUpFile()
                    {
                        Suc = true,
                        Msg = "上传成功",
                        File = new FileUp()
                        {
                            Id = fileUrl.Replace(_uploadConfig.VirtualPath, "").ToDesEncrypt(),
                            Path = fileUrl,
                            Name = fileName,
                            FileSuffix = ext,
                            FileType = fileType,
                            Size = file.Length
                        }
                    }.ToJsonStr());
                    #endregion 
                }
                catch (Exception ex)
                {
                    YzNLog.Error(ex);
                    await context.Response.WriteAsync(new VmUpFileBase()
                    {
                        Msg = "文件上传失败"
                    }.ToJsonStr());
                }
            }
            #endregion

            #region 非法上传
            else
            {
                await base.AddHttpNotAllowedAsync(context);
            }
            #endregion 
        }


    }
}
